package com.ahdms.es.gm.algorithm;

import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;
import java.security.SecureRandom;

public class SM2 {

    protected static final String[] ECC_PARAM = {
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
            "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
            "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
            "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
            "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"
    };

    private BigInteger eccP;
    private BigInteger eccA;
    private BigInteger eccB;
    private BigInteger eccN;
    private BigInteger eccGx;
    private BigInteger eccGy;
    private ECCurve eccCurve;
    private ECPoint eccPointG;
    private ECDomainParameters eccBcSpec;
    private ECKeyPairGenerator eccKeyPairGenerator;
    private ECFieldElement eccGxFieldelement;
    private ECFieldElement eccGyFieldelement;

    public BigInteger getEccP() {
        return eccP;
    }

    public BigInteger getEccA() {
        return eccA;
    }

    public BigInteger getEccB() {
        return eccB;
    }

    public BigInteger getEccN() {
        return eccN;
    }

    public BigInteger getEccGx() {
        return eccGx;
    }

    public BigInteger getEccGy() {
        return eccGy;
    }

    public ECCurve getEccCurve() {
        return eccCurve;
    }

    public ECPoint getEccPointG() {
        return eccPointG;
    }

    public ECDomainParameters getEccBcSpec() {
        return eccBcSpec;
    }

    public ECKeyPairGenerator getEccKeyPairGenerator() {
        return eccKeyPairGenerator;
    }

    public ECFieldElement getEccGxFieldelement() {
        return eccGxFieldelement;
    }

    public ECFieldElement getEccGyFieldelement() {
        return eccGyFieldelement;
    }

    private static SM2 instance = new SM2();

    private SM2() {
        init();
    }

    private void init() {
        eccP = new BigInteger(ECC_PARAM[0], 16);
        eccA = new BigInteger(ECC_PARAM[1], 16);
        eccB = new BigInteger(ECC_PARAM[2], 16);
        eccN = new BigInteger(ECC_PARAM[3], 16);
        eccGx = new BigInteger(ECC_PARAM[4], 16);
        eccGy = new BigInteger(ECC_PARAM[5], 16);

        eccCurve = new ECCurve.Fp(eccP, eccA, eccB);

        eccGxFieldelement = eccCurve.fromBigInteger(eccGx);
        eccGyFieldelement = eccCurve.fromBigInteger(eccGy);

        eccPointG = eccCurve.createPoint(eccGx, eccGy);
        eccBcSpec = new ECDomainParameters(eccCurve, eccPointG, eccN);

        eccKeyPairGenerator = new ECKeyPairGenerator();
        eccKeyPairGenerator.init(new ECKeyGenerationParameters(eccBcSpec, new SecureRandom()));
    }

    public static SM2 getInstance() {
        return instance;
    }

}
